package util;

import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;

/**
 * 简单的单例Bean管理器
 */
@SuppressWarnings("unchecked")
public class BeanManager {
	private static final HashMap<Class<?>, Object> BEANS_MAP = new HashMap<>();

	/**
	 * 通过类对象获取Bean对象，该类必须含有公开的空参构造器
	 *
	 * @param c   要获取的bean对象的类对象
	 * @param <T> bean对象类型
	 * @return 空参构造的对象
	 */
	public static <T> T getBean(Class<T> c) {
		// 如果是c是接口，则查找同级目录下impl是否有实现类，将c替换为找到的第一个实现类类对象
		// 接口就查找impl包下的实现类，我这里限制实现类必须为 接口名 + Impl
		Class<T> c2 = c;
		if (c2.isInterface()) {
			try {
				c2 = (Class<T>) Class.forName(c.getPackageName() + ".impl." + c.getSimpleName() + "Impl");
			} catch (ClassNotFoundException e) {
				throw new RuntimeException("没找到该接口的实现类，请确认将实现类放在该接口同级目录下的impl目录");
			}
		}

		Object o = BEANS_MAP.get(c2);
		if (o == null) {
			try {
				T t = c2.getDeclaredConstructor().newInstance();
				BEANS_MAP.put(c, t);
				if (c2 != c)
					BEANS_MAP.put(c2, t);
				o = t;
			} catch (InstantiationException | IllegalAccessException | InvocationTargetException |
			         NoSuchMethodException e) {
				throw new RuntimeException(e);
			}
		}
		return (T) o;
	}

	public static void addBean(Object o) {
		BEANS_MAP.put(o.getClass(), o);
	}
}
